{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "#----------------------------------拟合圆------------------------------------------#\n",
    "from numpy import *;#导入numpy的库函数\n",
    "import numpy as np; #这个方式使用numpy的函数时，需要以np.开头。\n",
    "\n",
    "def circleLeastFit(points):\n",
    "    center_x = 0.0\n",
    "    center_y = 0.0\n",
    "    radius = 0.0\n",
    "\n",
    "    sum_x = sum_y = 0.0\n",
    "    sum_x2 = sum_y2 = 0.0\n",
    "    sum_x3 = sum_y3 = 0.0\n",
    "    sum_xy = sum_x1y2 = sum_x2y1 = 0.0\n",
    "    N = len(points)\n",
    "    for i in range(1,N):\n",
    "        x = points[i][0]\n",
    "        y = points[i][1]\n",
    "        x2 = x * x\n",
    "        y2 = y * y\n",
    "        sum_x += x\n",
    "        sum_y += y\n",
    "        sum_x2 += x2\n",
    "        sum_y2 += y2\n",
    "        sum_x3 += x2 * x\n",
    "        sum_y3 += y2 * y\n",
    "        sum_xy += x * y\n",
    "        sum_x1y2 += x * y2\n",
    "        sum_x2y1 += x2 * y\n",
    "\n",
    "    C = D = E = G = H =0.0\n",
    "    a = b = c = 0.0\n",
    "    C = N * sum_x2 - sum_x * sum_x\n",
    "    D = N * sum_xy - sum_x * sum_y\n",
    "    E = N * sum_x3 + N * sum_x1y2 - (sum_x2 + sum_y2) * sum_x\n",
    "    G = N * sum_y2 - sum_y * sum_y\n",
    "    H = N * sum_x2y1 + N * sum_y3 - (sum_x2 + sum_y2) * sum_y\n",
    "    a = (H * D - E * G) / (C * G - D * D)\n",
    "    b = (H * C - E * D) / (D * D - G * C)\n",
    "    c = -(a * sum_x + b * sum_y + sum_x2 + sum_y2) / N\n",
    "    \n",
    "    center_x = a / (-2)\n",
    "    center_y = b / (-2)\n",
    "    radius = sqrt(a * a + b * b - 4 * c) / 2\n",
    "    \n",
    "    return center_x, center_y, round(radius,2)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-0.006578947368421052 -0.2894736842105263 1.03\n"
     ]
    }
   ],
   "source": [
    "#--------------------------------测试拟合圆-------------------------------------#\n",
    "list = []\n",
    "list.append([-1,0])\n",
    "list.append([0,1])\n",
    "list.append([-1,0])\n",
    "list.append([0,-1.5])\n",
    "\n",
    "x, y, r = circleLeastFit(list);\n",
    "print(x,y,r)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "#----------------------------------官网示例代码--------------------------------------#\n",
    "# -*- coding: utf-8 -*-\n",
    "import urllib.request\n",
    "import urllib.error\n",
    "import time\n",
    "import json\n",
    "\n",
    "http_url = 'https://api-cn.faceplusplus.com/facepp/v3/detect'\n",
    "key = \"enFC8NNZcf19CNRZGhGMvGKPHtMgVkfB\"\n",
    "secret = \"kIV15LIXTSX0gKflGEYHXekj8-mgEuHE\"\n",
    "filepath = r\"gg.jpg\"\n",
    "\n",
    "boundary = '----------%s' % hex(int(time.time() * 1000))\n",
    "data = []\n",
    "data.append('--%s' % boundary)\n",
    "data.append('Content-Disposition: form-data; name=\"%s\"\\r\\n' % 'api_key')\n",
    "data.append(key)\n",
    "\n",
    "data.append('--%s' % boundary)\n",
    "data.append('Content-Disposition: form-data; name=\"%s\"\\r\\n' % 'api_secret')\n",
    "data.append(secret)\n",
    "\n",
    "data.append('--%s' % boundary)\n",
    "fr = open(filepath, 'rb')\n",
    "data.append('Content-Disposition: form-data; name=\"%s\"; filename=\" \"' % 'image_file')\n",
    "data.append('Content-Type: %s\\r\\n' % 'application/octet-stream')\n",
    "data.append(fr.read())\n",
    "fr.close()\n",
    "data.append('--%s' % boundary)\n",
    "data.append('Content-Disposition: form-data; name=\"%s\"\\r\\n' % 'return_landmark')\n",
    "data.append('2')\n",
    "data.append('--%s' % boundary)\n",
    "data.append('Content-Disposition: form-data; name=\"%s\"\\r\\n' % 'return_attributes')\n",
    "data.append(\n",
    "    \"gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus\")\n",
    "data.append('--%s--\\r\\n' % boundary)\n",
    "\n",
    "for i, d in enumerate(data):\n",
    "    if isinstance(d, str):\n",
    "        data[i] = d.encode('utf-8')\n",
    "\n",
    "http_body = b'\\r\\n'.join(data)\n",
    "\n",
    "# build http request\n",
    "req = urllib.request.Request(url=http_url, data=http_body)\n",
    "\n",
    "# header\n",
    "req.add_header('Content-Type', 'multipart/form-data; boundary=%s' % boundary)\n",
    "\n",
    "try:\n",
    "    # post data to server\n",
    "    resp = urllib.request.urlopen(req, timeout=5)\n",
    "    # get response\n",
    "    qrcont = resp.read()\n",
    "    # if you want to load as json, you should decode first,\n",
    "    # for example: json.loads(qrcont.decode('utf-8'))\n",
    "    text=json.loads(qrcont.decode('utf-8'))\n",
    "    text1=text.get('faces')[0].get('landmark')\n",
    "except urllib.error.HTTPError as e:\n",
    "    print(e.read().decode('utf-8'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "contour_left1\n",
      "{'y': 109, 'x': 214}\n",
      "contour_left2\n",
      "{'y': 114, 'x': 214}\n",
      "contour_left3\n",
      "{'y': 119, 'x': 214}\n",
      "contour_left4\n",
      "{'y': 124, 'x': 215}\n",
      "contour_left5\n",
      "{'y': 128, 'x': 216}\n",
      "contour_left6\n",
      "{'y': 133, 'x': 216}\n",
      "[[214, 109], [214, 114], [214, 119], [215, 124], [216, 128], [216, 133]]\n",
      "61.08006763040394 142.7323317195069 1.03\n"
     ]
    }
   ],
   "source": [
    "list1=[]\n",
    "for i in range(6):\n",
    "    print('contour_left'+str(i+1))\n",
    "    text2=text1.get('contour_left'+str(i+1))\n",
    "    print(text2)\n",
    "    list1.append([text2.get('x'),text2.get('y')])\n",
    "print(list1)\n",
    "x, y, r1 = circleLeastFit(list1);\n",
    "print(x,y,r1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "contour_left7\n",
      "{'y': 138, 'x': 217}\n",
      "contour_left8\n",
      "{'y': 143, 'x': 219}\n",
      "contour_left9\n",
      "{'y': 147, 'x': 220}\n",
      "contour_left10\n",
      "{'y': 151, 'x': 223}\n",
      "contour_left11\n",
      "{'y': 155, 'x': 226}\n",
      "contour_left12\n",
      "{'y': 158, 'x': 230}\n",
      "contour_left13\n",
      "{'y': 161, 'x': 234}\n",
      "[[217, 138], [219, 143], [220, 147], [223, 151], [226, 155], [230, 158], [234, 161]]\n",
      "-119.46706252169488 419.7217814195973 1.03\n"
     ]
    }
   ],
   "source": [
    "list2=[]\n",
    "for i in range(7,14):\n",
    "    print('contour_left'+str(i))\n",
    "    text2=text1.get('contour_left'+str(i))\n",
    "    print(text2)\n",
    "    list2.append([text2.get('x'),text2.get('y')])\n",
    "print(list2)\n",
    "x, y, r2 = circleLeastFit(list2);\n",
    "print(x,y,r2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "contour_left14\n",
      "{'y': 164, 'x': 238}\n",
      "contour_right14\n",
      "{'y': 164, 'x': 268}\n",
      "contour_left15\n",
      "{'y': 167, 'x': 242}\n",
      "contour_right15\n",
      "{'y': 167, 'x': 264}\n",
      "contour_left16\n",
      "{'y': 168, 'x': 247}\n",
      "contour_right16\n",
      "{'y': 169, 'x': 259}\n",
      "contour_chin\n",
      "{'y': 169, 'x': 253}\n",
      "[[238, 164], [268, 164], [242, 167], [264, 167], [247, 168], [259, 169], [253, 169]]\n",
      "226.86766216582257 -67.31153311932896 1.03\n"
     ]
    }
   ],
   "source": [
    "\n",
    "list2=[]\n",
    "for i in range(14,17):\n",
    "    print('contour_left'+str(i))\n",
    "    text2=text1.get('contour_left'+str(i))\n",
    "    print(text2)\n",
    "    list2.append([text2.get('x'),text2.get('y')])\n",
    "    print('contour_right'+str(i))\n",
    "    text3=text1.get('contour_right'+str(i))\n",
    "    print(text3)\n",
    "    list2.append([text3.get('x'),text3.get('y')])\n",
    "print('contour_chin')\n",
    "text4=text1.get('contour_chin')\n",
    "print(text4)\n",
    "list2.append([text4.get('x'),text4.get('y')])\n",
    "print(list2)\n",
    "x, y, r3 = circleLeastFit(list2);\n",
    "print(x,y,r3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "74 75 65 56 155.25 436.32 236.58\n"
     ]
    }
   ],
   "source": [
    "#----------------------------------只计算x或y------------------------------------------#\n",
    "w1=text1.get('contour_right1').get('x')-text1.get('contour_left1').get('x')\n",
    "w2=text1.get('contour_right3').get('x')-text1.get('contour_left3').get('x')\n",
    "w3=text1.get('contour_right9').get('x')-text1.get('contour_left9').get('x')\n",
    "h=text1.get('contour_chin').get('y')-text1.get('nose_bridge1').get('y')\n",
    "print(w1,w2,w3,h,r1,r2,r3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "74.06 75.06 65.01 56.14 155.25 436.32 236.58\n"
     ]
    }
   ],
   "source": [
    "#----------------------------------都计算,欧式距离------------------------------------------#\n",
    "w1=round(sqrt((text1.get('contour_right1').get('x')-text1.get('contour_left1').get('x'))**2+(text1.get('contour_right1').get('y')-text1.get('contour_left1').get('y'))**2),2)\n",
    "w2=round(sqrt((text1.get('contour_right3').get('x')-text1.get('contour_left3').get('x'))**2+(text1.get('contour_right3').get('y')-text1.get('contour_left3').get('y'))**2),2)\n",
    "w3=round(sqrt((text1.get('contour_right9').get('x')-text1.get('contour_left9').get('x'))**2+(text1.get('contour_right9').get('y')-text1.get('contour_left9').get('y'))**2),2)\n",
    "h=round(sqrt((text1.get('contour_chin').get('x')-text1.get('nose_bridge1').get('x'))**2+(text1.get('contour_chin').get('y')-text1.get('nose_bridge1').get('y'))**2),2)\n",
    "print(w1,w2,w3,h,r1,r2,r3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "history\n",
      "history\n"
     ]
    }
   ],
   "source": [
    "#--------------------------------------检测与结果输出------------------------------------------#\n",
    "import csv\n",
    "import numpy as np\n",
    "import operator as op\n",
    "\n",
    "csv_in = pd.read_csv('../labels/output_2.csv', sep = ',', header = None)\n",
    "csv_in = csv_in.values\n",
    "img_name = csv_in[:, 1]\n",
    "img_labl = csv_in[:, 7]\n",
    "print(img_name.shape[0])\n",
    "\n",
    "csv_out = open('result_2.csv', 'w', newline = '')\n",
    "csv_write = csv.writer(csv_out, dialect = 'excel')\n",
    "head = ['id', 'name', 'origin', 'result','accuracy rate']\n",
    "csv_write.writerow(head)\n",
    "\n",
    "csv_out = open('result_2.csv', 'a', newline = '')\n",
    "csv_write = csv.writer(csv_out, dialect = 'excel')\n",
    "\n",
    "cntyes = 0\n",
    "for i in range(1, img_name.shape[0]):\n",
    "    \n",
    "    img_src = '../images/' + img_name[i][0:3] + '/' + img_name[i]\n",
    "    faceDetect = KNNIndentify(img_src)\n",
    "      \n",
    "    if(op.eq(img_labl[i], faceDetect)):\n",
    "        cntyes = cntyes + 1\n",
    "        \n",
    "    eachrow = [i, img_name[i], img_labl[i], faceDetect]\n",
    "    csv_write.writerow(eachrow)\n",
    "    \n",
    "eachrow = ['-', '-', '-', '-',cntyes/img_name.shape[0]]\n",
    "csv_write.writerow(eachrow)\n",
    "    \n",
    "csv_out.close()\n",
    "  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#--------------------------------测试face++ api (失败）-------------------------------------#\n",
    "#!/usr/bin/env python\n",
    "# -*- coding: utf-8 -*-\n",
    "import requests\n",
    "import json\n",
    "import base64\n",
    "\n",
    "class FaceIdentify:\n",
    "    def __init__(self,img):\n",
    "        self.AK = \"enFC8NNZcf19CNRZGhGMvGKPHtMgVkfB\"\n",
    "        self.SK = \"kIV15LIXTSX0gKflGEYHXekj8-mgEuHE\"\n",
    "        self.img_src = img\n",
    "        self.headers = {\n",
    "            \"Content-Type\": \"application/json; charset=UTF-8\"\n",
    "        }\n",
    "#         headers = {'content-type': \"application/json\", 'Authorization': 'APP appid = 4abf1a,token = 9480295ab2e2eddb8'}\n",
    "    \n",
    "    def img_to_BASE64(self,path):\n",
    "        with open(path,'rb') as f:\n",
    "            base64_data = base64.b64encode(f.read())\n",
    "            return base64_data\n",
    "           \n",
    "    def detect_face(self):\n",
    "        img_BASE64 = self.img_to_BASE64(self.img_src)\n",
    "#         print(img_BASE64)\n",
    "        url = 'https://api-cn.faceplusplus.com/facepp/v3/detect'\n",
    "        body = {\n",
    "            \"api_key\": self.AK, \n",
    "            \"api_secret\": self.SK,\n",
    "            \"image_base64\":img_BASE64,\n",
    "            \"return_landmark\":2\n",
    "        }\n",
    "        response = requests.post(url, data = body, headers=self.headers)\n",
    "        print(response)\n",
    "        json_result = json.loads(response.text)\n",
    "        return json_result\n",
    "img_src = '../images/test.jpg'\n",
    "faceDetect = FaceIdentify(img_src)\n",
    "faceDetect.detect_face()\n",
    "# obj = faceDetect.detect_face()\n",
    "# print(obj)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
